using System;

namespace Fadd.Components
{
    /// <summary>
    /// A found plugin and which of the requested types that it implements.
    /// </summary>
    [Serializable]
    public class ComponentTypeInfo
    {
        private readonly string _assembly;
        private readonly string _publicKey;
        private readonly byte[] _publicKeyRaw;
        private readonly Type _instanceType;
        private readonly Type _interfaceType;
        private readonly bool _isPrivate;

        /// <summary>
        /// Initializes a new instance of the <see cref="ComponentTypeInfo"/> class.
        /// </summary>
        /// <param name="assemblyLocation">assembly that the plugin resides in.</param>
        /// <param name="publicKey">assemblies public key. should be used to decide the amount of access for the module.</param>
        /// <param name="instanceType">Type to create</param>
        /// <param name="interfaceType">Type used when fetching the component</param>
        /// <exception cref="ArgumentNullException">types or assembly location is null.</exception>
        public ComponentTypeInfo(string assemblyLocation, byte[] publicKey, Type instanceType, Type interfaceType)
        {
            if (assemblyLocation == null)
                throw new ArgumentNullException("assemblyLocation");
            if (interfaceType == null)
                throw new ArgumentNullException("interfaceType");

            _interfaceType = interfaceType;
            _instanceType = instanceType;
            _assembly = assemblyLocation;
            _publicKey = string.Empty;
            _publicKeyRaw = publicKey;
            if (publicKey == null) return;
            for (int i = 0; i < publicKey.Length; ++i)
                _publicKey += publicKey[i].ToString("x2");
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ComponentTypeInfo"/> class.
        /// </summary>
        /// <param name="assemblyLocation">assembly that the plugin resides in.</param>
        /// <param name="publicKey">assemblies public key. should be used to decide the amount of access for the module.</param>
        /// <param name="instanceType">Type to create</param>
        /// <param name="interfaceType">Type used when fetching the component</param>
        /// <param name="isPrivate">Component is private</param>
        /// <exception cref="ArgumentNullException">types or assembly location is null.</exception>
        public ComponentTypeInfo(string assemblyLocation, byte[] publicKey, Type instanceType, Type interfaceType, bool isPrivate)
        {
            if (assemblyLocation == null)
                throw new ArgumentNullException("assemblyLocation");
            if (interfaceType == null)
                throw new ArgumentNullException("interfaceType");

            _interfaceType = interfaceType;
            _isPrivate = isPrivate;
            _instanceType = instanceType;
            _assembly = assemblyLocation;
            _publicKey = string.Empty;
            _publicKeyRaw = publicKey;
            if (publicKey == null) return;
            for (int i = 0; i < publicKey.Length; ++i)
                _publicKey += publicKey[i].ToString("x2");
        }

        /// <summary>
        /// Gets the assembly's public key (if signed).
        /// </summary>
        public string PublicKey
        {
            get { return _publicKey; }
        }

        /// <summary>
        /// Gets location of DLL.
        /// </summary>
        public string Location
        {
            get { return _assembly; }
        }

        /// <summary>
        /// Gets assembly public key in byte format.
        /// </summary>
        public byte[] PublicKeyRaw
        {
            get { return _publicKeyRaw; }
        }

        /// <summary>
        /// Gets a the type used when accessing the component.
        /// </summary>
        public Type InterfaceType
        {
            get { return _interfaceType; }
        }

        /// <summary>
        /// Gets the type to create
        /// </summary>
        public Type InstanceType
        {
            get { return _instanceType; }
        }

        /// <summary>
        /// Gets a value indicating whether the component is private.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if the component is private; otherwise, <c>false</c>.
        /// </value>
        public bool IsPrivate
        {
            get { return _isPrivate; }
        }
    }
}
